package khleuven.mondzorg.domain;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;

public class Entries {
	
	private ArrayList<Entry> allEntries;
	
	private HashMap<EntryType, HashSet<Entry>> allEntriesByType;
	private HashMap<Language, HashSet<Entry>> allEntriesByLanguage;
	private HashMap<DestinationGroup, HashSet<Entry>> allEntriesByDestination;

	public Entries() {
		allEntries = new ArrayList<Entry>();
		
		allEntriesByType = new HashMap<EntryType, HashSet<Entry>>();
		allEntriesByLanguage = new HashMap<Language, HashSet<Entry>>();
		allEntriesByDestination = new HashMap<DestinationGroup, HashSet<Entry>>();
	}
	
	public ArrayList<Entry> getAllEntries() {
		return allEntries;
	}
	
	public HashSet<Entry> getAllEntries(EntryType type){
		HashSet<Entry> r = allEntriesByType.get(type);
		if(r == null) {
			return new HashSet<Entry>();
		} else {
			return r;
		}
	}
	
	public void add(Entry entry) {
		allEntries.add(entry);
		
		HashSet<Entry> entriest = allEntriesByType.get(entry.getType());
		if( entriest == null){
			entriest = new HashSet<Entry>();
			entriest.add(entry);
			allEntriesByType.put(entry.getType(), entriest);
		} else{
			entriest.add(entry);
		}
		
		HashSet<Entry> entriesl = allEntriesByLanguage.get(entry.getLanguage());
		if( entriesl == null){
			entriesl = new HashSet<Entry>();
			entriesl.add(entry);
			allEntriesByLanguage.put(entry.getLanguage(), entriesl);
		} else{
			entriesl.add(entry);
		}
		
		HashSet<Entry> entriesd = allEntriesByDestination.get(entry.getDestination());
		if( entriesd == null){
			entriesd = new HashSet<Entry>();
			entriesd.add(entry);
			allEntriesByDestination.put(entry.getDestination(), entriesd);
		} else{
			entriesd.add(entry);
		}	
	}

	public HashSet<Entry> getPreferredEntries(EntryType type, Language language, DestinationGroup destination) {
		HashSet<Entry> preferredEntries = new HashSet<Entry>();
		
		HashSet<Entry> entriest = allEntriesByType.get(type);
		// if type not present: return empty list.
		if(entriest != null && entriest.size() != 0) {
			HashSet<Entry> entriesl = allEntriesByLanguage.get(language);
			HashSet<Entry> entriesd = allEntriesByDestination.get(destination);
			
			preferredEntries.addAll(entriest);
			preferredEntries.retainAll(entriesl);
			preferredEntries.retainAll(entriesd);
		}
		return preferredEntries;		
	}

	public ArrayList<String> getPreferredEntriesAsStringList(
			EntryType type, Language language, DestinationGroup destination) {
		ArrayList<String> prefentriesstrings = new ArrayList<String>();
		HashSet<Entry> prefentries = getPreferredEntries(type, language, destination);
		for(Entry entry: prefentries){
			prefentriesstrings.add(entry.makeStringForList());
		}
		return prefentriesstrings;
	}
	
	public Entry getEntry(EntryType type, String listedString, Language language, DestinationGroup destination) {
		Entry wantedEntry = null;
		HashSet<Entry> prefentries = getPreferredEntries(type, language, destination);
		for(Entry entry: prefentries){
			// Making sure "Gezonde voeding" en "gezonde voeding" matches
			if(entry.makeStringForList().equalsIgnoreCase(listedString)){
				wantedEntry = entry;
			}
		}
		return wantedEntry;
	}
	
	
	public Illustrations getEntryIllustrations(EntryType type, String listedString, Language language, DestinationGroup destination){
		Entry entry = getEntry(type, listedString, language, destination);
		return entry.getIllustrations();
	}

	/**
	 * Get the total number of language and target independent entries per EntryType
	 * Mostly used for testing purposes.
	 */
	public LinkedHashMap<EntryType, Integer> getNbOfEntriesPerType() {
		LinkedHashMap<EntryType, Integer> result = new LinkedHashMap<EntryType, Integer>();
		// tel het aantal entries per types
		for(EntryType t : this.allEntriesByType.keySet()) {
			if(!result.containsKey(t)) {
				result.put(t, allEntriesByType.get(t).size());
			} else {
				throw new RuntimeException(); // should not occur
			}
		}
			
		return result;
	}





}
